package org.estela.ml.dataset;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;


/**
 * 
 * @version 1.00
 * @date Apr 23, 2006
 * @author <a href="mailto:akantek@nyse.com">Antonio Kantek</a>
 */
public class ArffParser implements DataSetParser {

	private Logger _log = Logger.getLogger(getClass().getName());

	/** */
	private BufferedReader reader;

	/** */
	private String dataSetName;

	/** */
	private Attribute[] attributes;

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		InputStream in = new FileInputStream(args[0]);
		ArffParser parser = new ArffParser(in);
		Instance instance;
		while ((instance = parser.nextRow()) != null) {
			System.out.println(instance);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see dataset.parsers.DataSetParser#parse(java.io.InputStream)
	 */
	public ArffParser(InputStream in) throws IOException {
		_log.finest("in=" + in);
		this.reader = new BufferedReader(new InputStreamReader(in));
		String line;
		int attrIdx = 0;
		List<Attribute> attributesTemp = new LinkedList<Attribute>();
		while ((line = this.reader.readLine()) != null) {
			line = line.trim();
			if (line.startsWith("%")) {
				continue;
			}
			if (line.equals("@data")) {
				break;
			}
			if (line.length() == 0) {
				continue;
			}
			String[] tokens = line.split(" ");
			if (tokens[0].equals("@relation")) {
				this.dataSetName = tokens[1];
				_log.info("dataSetName=" + this.dataSetName);
				continue;
			}
			if (tokens[0].equals("@attribute")) {
				if (tokens[2].equals("real")) {
					ContinuousAttribute contAttribute = new ContinuousAttribute(
							attrIdx++, tokens[1]);
					attributesTemp.add(contAttribute);
					_log.info("attribute=" + contAttribute);
				} else {
					String[] categories = line.substring(line.indexOf('{')+1, line.indexOf('}')).split("\\s?,\\s?");
					DiscreteAttribute discreteAttribute = new DiscreteAttribute(
							attrIdx++, tokens[1], categories);
					attributesTemp.add(discreteAttribute);
					_log.info("attribute=" + discreteAttribute);
				}
			}
		}
		this.attributes = attributesTemp.toArray(new Attribute[attributesTemp.size()]);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see dataset.parsers.DataSetParser#getDataSetName()
	 */
	public String getDataSetName() {
		return this.dataSetName;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see dataset.parsers.DataSetParser#getAttributes()
	 */
	public Attribute[] getAttributes() {
		return this.attributes;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see dataset.parsers.DataSetParser#nextRow()
	 */
	public Instance nextRow() throws IOException {
		Instance instance = null;
		String line;
		while ((line = this.reader.readLine()) != null) {
			line = line.trim();
			if (line.length() == 0) {
				continue;
			}
			if (line.startsWith("%")) {
				continue;
			}
			
			String[] values = line.split(",");
			double[] encoded = new double[this.attributes.length];
			for (int i = 0; i < this.attributes.length; i++) {
				encoded[i] = this.attributes[i].encode(values[i]);
			}
			instance = new Instance(encoded);
			break;
		}
		_log.info("instance=" + instance);
		return instance;
	}
}
